import json
import os

import pandas as pd
import torchaudio
import numpy as np
from flask import Flask, abort, redirect, request, jsonify, render_template, send_from_directory, url_for, session
from werkzeug.utils import secure_filename

from models.draw import ClassificationModel
from models.main import ModelEval, ModelTrain
from models.utils import fstr2float, check_csv, rm_all
# from models.utils import *
import warnings

warnings.filterwarnings("ignore")

app = Flask(__name__)
app.secret_key = 'your_secret_key'
basedir = os.path.abspath(os.path.dirname(__file__))  # 获得当前项目的绝对地址

app.config['SECRET_KEY'] = 'some strange words'  # 设置密钥
app.config['UPLOAD_FOLDER'] = 'upload/test_datasets'  # 保存文件的地址
app.config['UPLOAD_EXTENSIONS'] = set(['csv'])


# def default_dump(obj):
#     """Convert numpy classes to JSON serializable objects."""
#     if isinstance(obj, (np.integer, np.floating, np.bool_)):
#         return obj.item()
#     elif isinstance(obj, np.ndarray):
#         return obj.tolist()
#     else:
#         return obj


def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in app.config['UPLOAD_EXTENSIONS']


@app.route('/', methods=['POST', 'GET'])
def index():
    return render_template('主页.html')


# 上传文件接口
@app.route('/upload_test', methods=['POST', 'GET'])
def upload_test():
    result = "test_data.json"
    entries = []
    if (request.method == 'GET'):
        entries_2 = os.listdir('./static/params')
        for entry in entries_2:
            entry = entry.rsplit('.', 1)[0]
            entries.append(entry)
        success_msg = session.pop('success_msg', None)
        response = jsonify({'message': 'File uploaded successfully'})
        response.status_code = 200
        return render_template("测试.html", entries=entries, result=result, success_msg=success_msg)
    file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER'])
    # 获取上传的文件

    file = request.files['test-file']
    username = str(request.form.get("model_name"))
    print(username)
    filename = secure_filename(file.filename)  # secure_filename()函数将会对传入的文件路径进行处理，将其中的路径符号“/”用下划线代替，防止被黑客恶意攻击
    filepath = os.path.join(file_dir, filename)

    # 保存文件到本    file.save(filepath)

    # 操作文件
    if file and allowed_file(file.filename) and check_csv(filepath, True):
        s = "用户数据集" + filename + "已上传完毕"
        print(s)
        print('1')
        # 测试
        filename1 = filename.rsplit('.', 1)[0]
        model_eval = ModelEval(username, filename1)
        [json_file, json_path] = model_eval.predict()

        classification_model = ClassificationModel(json_path)  # 这里的 json_path 是你的数据文件路径
        classification_model.count_and_plot_results()
        # 直方图
        classification_model.bar_plot("static/html_tmp_1/bar.html")

        # 扇形图-玫瑰图
        classification_model.pie_plot_2("static/html_tmp_1/pie2.html")

        # 面积分割图
        classification_model.treemap_plot("static/html_tmp_1/treemap.html")

        # 水球图
        for i in range(6):
            file_name = f"liquid{i}.html"
            classification_model.liquid(i, 'static/html_tmp_1/' + file_name)
        response = jsonify({'message': 'File uploaded successfully'})
        response.status_code = 200
        entries_2 = os.listdir('./static/params')
        for entry in entries_2:
            entry = entry.rsplit('.', 1)[0]
            entries.append(entry)
        # print(result)
        # print('2')
        success_msg = session.pop('success_msg', None)
        return render_template("测试.html", entries=entries, result=result, success_msg=success_msg)
    else:
        # 返回错误的响应
        response = jsonify({'message': 'Invalid file type'})
        response.status_code = 400
        return response


# 利用保存的模型文件进行训练
@app.route('/upload_train', methods=['POST', 'GET'])
def upload_train():
    if (request.method == 'GET'):
        entries = os.listdir('./static/params')
        success_msg = session.pop('success_msg', None)
        response = jsonify({'message': 'File uploaded successfully'})
        response.status_code = 200
        return render_template("训练.html", entries_1=entries)
    file_dir = os.path.join(basedir, 'upload/train_datasets')
    # 获取上传的文件
    file1 = request.files["train-file1"]
    file2 = request.files["train-file2"]
    flag = 0
    entries_2 = os.listdir('./static/params')
    if (file2.filename == ''):
        flag = 1;
    else:
        filename2 = secure_filename(file2.filename)  # secure_filename()函数将会对传入的文件路径进行处理，将其中的路径符号“/”用下划线代替，防止被黑客恶意攻击
        filepath2 = os.path.join(file_dir, filename2)
        # 保存文件到本地磁盘
        file2.save(filepath2)
    username = str(request.form.get("model_name"))
    lr = float(request.form.get("lr"))
    l1_penalty = float(request.form.get("l1_penalty"))
    l2_penalty = float(request.form.get("l2_penalty"))
    epochs = int(request.form.get("epochs"))
    loss_weight = []
    loss_weight1 = fstr2float(request.form.get("loss_weight1"))
    loss_weight2 = fstr2float(request.form.get("loss_weight2"))
    loss_weight3 = fstr2float(request.form.get("loss_weight3"))
    loss_weight4 = fstr2float(request.form.get("loss_weight4"))
    loss_weight5 = fstr2float(request.form.get("loss_weight5"))
    loss_weight6 = fstr2float(request.form.get("loss_weight6"))
    loss_weight.append(loss_weight1), loss_weight.append(loss_weight2), loss_weight.append(loss_weight3), loss_weight.append(
        loss_weight4), loss_weight.append(loss_weight5), loss_weight.append(loss_weight6)
    step_size = int(request.form.get("step_size"))
    gamma = float(request.form.get("gamma"))
    momentum = float(request.form.get("momentum"))
    filename1 = secure_filename(file1.filename)  # secure_filename()函数将会对传入的文件路径进行处理，将其中的路径符号“/”用下划线代替，防止被黑客恶意攻击
    filepath = os.path.join(file_dir, filename1)
    # 保存文件到本地磁盘
    file1.save(filepath)
    # file = request.files['train-file']
    # 操作文件

    if file1 and allowed_file(file1.filename) and check_csv(filepath, False):
        s = "用户数据集" + filename1 + "已上传完毕"
        print(s)
        filename1 = filename1.rsplit('.', 1)[0]
        if flag == 1:
            model_train = ModelTrain(username,
                                     filename1,
                                     "",
                                     1024,
                                     lr=lr,
                                     l1_penalty=l1_penalty,
                                     l2_penalty=l2_penalty,
                                     epochs=epochs,
                                     step_size=step_size,
                                     gamma=gamma,
                                     momentum=momentum)
        elif file2 and allowed_file(file2.filename) and check_csv(filepath2, False):
            s = "用户数据集" + filename2 + "已上传完毕"
            print(s)
            model_train = ModelTrain(username,
                                     filename1,
                                     filename2,
                                     1024,
                                     lr=lr,
                                     l1_penalty=l1_penalty,
                                     l2_penalty=l2_penalty,
                                     epochs=epochs,
                                     loss_weight=loss_weight,
                                     step_size=step_size,
                                     gamma=gamma,
                                     momentum=momentum)

        else:
            response = jsonify({'message': 'Invalid file type'})
            response.status_code = 400
            return response
        # 返回成功的响应
        loss_set = model_train.train()
        print(loss_set)
        loss1 = str(round(loss_set[0][0][0], 3))
        loss2 = str(round(loss_set[0][0][1], 3))
        loss3 = str(round(loss_set[0][1][0], 3))
        loss4 = str(round(loss_set[0][1][1], 3))
        loss5 = str(round(loss_set[1][0][0], 3))
        loss6 = str(round(loss_set[1][0][1], 3))
        loss7 = str(round(loss_set[1][1][0], 3))
        loss8 = str(round(loss_set[1][1][1], 3))
        response = jsonify({'message': 'File uploaded successfully'})
        response.status_code = 200
        loss_dict = {
            'loss1': loss1,
            'loss2': loss2,
            'loss3': loss3,
            'loss4': loss4,
            'loss5': loss5,
            'loss6': loss6,
            'loss7': loss7,
            'loss8': loss8,
        }
        print(loss_dict)
        return jsonify(loss=loss_dict)
        # file_name = username + ".pth"
        # return render_template('训练.html',
        #                        file_name=file_name,
        #                        entries_1=entries_2,
        #                        loss1=loss1,
        #                        loss2=loss2,
        #                        loss3=loss3,
        #                        loss4=loss4,
        #                        loss5=loss5,
        #                        loss6=loss6,
        #                        loss7=loss7,
        #                        loss8=loss8)
    else:
        # 返回错误的响应
        response = jsonify({'message': 'Invalid file type'})
        response.status_code = 400
        return response


@app.route('/download_file', methods=["post"])
def downloadFile():
    model_name = request.form.get("downloadModel")
    return send_from_directory('./static/params', model_name, as_attachment=True)


# 下载数据集
@app.route('/files_model/<filename>')
def files1(filename):
    return send_from_directory('./static/params', filename, as_attachment=True)


# 下载数据集
@app.route('/files_json/<filename>')
def files2(filename):
    return send_from_directory('./static/jsons', filename, as_attachment=True)


# import jsonpath
# def get_json_value(json_data, key_name):
#     '''获取到json中任意key的值,结果为list格式'''
#     key_value = jsonpath.jsonpath(json_data, '$..{key_name}'.format(key_name=key_name))
#     # key的值不为空字符串或者为empty（用例中空固定写为empty）返回对应值，否则返回empty
#
#     return key_value
#

@app.route('/get_data', methods=['GET'])
def get_data():
    input_data = request.args.get('data')  # 获取前端传递的数据
    s = json.load(open('static/jsons/test_data.json', 'r', encoding='utf-8'))
    length = len(s)
    print(length)
    # print(input_data)
    # print(length)
    # print(type(input_data))
    # print(type(length))
    if (int(input_data) > length - 1):
        result = "输入的id值不在范围内，正确的范围为0-" + str(length - 1)
        return result
    output_data = s[input_data]
    # 在此处执行相应的数据查询逻辑，获取对应的数据
    if (input_data == 0):
        result = "查询结果: 序号" + str(input_data) + "样本的类型为正常"
    else:
        result = "查询结果: 序号" + str(input_data) + "样本的类型为故障" + str(output_data)

    return result


@app.route('/get_file', methods=['POST'])
def get_file():
    file = request.files['file']  # 获取上传的文件对象
    file_name = file.filename
    f = pd.read_csv("upload/test_datasets/" + file_name, header=0, index_col=0)
    print(f)
    f_knum = len(f)
    del f
    # 在此处执行文件处理逻辑，例如读取文件内容、分析数据等
    data = "测试集行数：" + str(f_knum) + "  " + "(查询序号有效范围 : [ 0," + str(f_knum - 1) + " ])"

    return data


@app.route('/upload', methods=['POST'])
def upload_file():
    # 处理文件上传逻辑
    return 'File uploaded successfully.'


@app.route('/show_result', methods=['POST', 'GET'])
def show_result():
    if (request.method == 'GET'):
        return render_template("结果可视化.html")


@app.route('/pro_info', methods=['POST', 'GET'])
def pro_info():
    if (request.method == 'GET'):
        return render_template("产品说明.html")


@app.route("/get_table", methods=["GET"])
def query_table():
    classification_model = ClassificationModel('static/jsons/test_data.json')  # 这里的 file_path 是你的数据文件路径
    classification_model.count_and_plot_results()  # 处理数据
    data_dict = classification_model.generate_dict()
    return jsonify(data_dict)


@app.route('/results_label', methods=['GET'])
def get_results_label():
    index = request.args.get('index')

    file_path = os.path.join(basedir, 'static', 'jsons', 'test_data.json')
    classification_model = ClassificationModel(file_path)  # 这里的 file_path 是你的数据文件路径
    classification_model.count_and_plot_results()  # 处理数据
    results_label = classification_model.results_label  # 获取 self.results_label 列表

    index = int(index)
    return jsonify(results_label=results_label[index])


@app.route('/delete_model', methods=['post'])
def delete_model():
    data = request.form.get("deleteModel")
    file_path = "./static/params/" + data + ".pth"
    os.remove(file_path)
    success_msg = f"模型文件'{data}.pth' 已被成功删除"
    session['success_msg'] = success_msg
    return redirect('/upload_test')


# @app.before_first_request
def initialize():
    # 在第一个请求之前执行的函数
    # print("函数已被调用")
    rm_all("./static/pics")


if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True, port='5000')
